]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
weather: Stop accessing app settings directly
authorFlorian Müllner <fmuellner@gnome.org>
Tue, 23 Jul 2019 10:49:40 +0000 (10:49 +0000)
committerFlorian Müllner <florian.muellner@gmail.com>
Wed, 31 Jul 2019 19:04:41 +0000 (19:04 +0000)
Our current Weather integration depends on poking around the app's
settings, which we cannot do when the app is sandboxed (as its
filesystem is "hidden away" in a container in that case).

So instead, use our own GSettings schema for the settings, and sync
it with GNOME Weather via a custom D-Bus interface.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158

data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml [new file with mode: 0644]
data/gnome-shell-dbus-interfaces.gresource.xml
data/org.gnome.shell.gschema.xml.in
js/misc/weather.js

diff --git a/data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml b/data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
new file mode 100644 (file)
index 0000000..1e89bbe
--- /dev/null
@@ -0,0 +1,16 @@
+<node>
+
+  <!--
+      org.gnome.Shell.WeatherIntegration:
+      @short_description: Weather integration interface
+
+      The interface used for exporting location settings to GNOME Shell's
+      weather integration.
+  -->
+  <interface name="org.gnome.Shell.WeatherIntegration">
+
+  <property name="AutomaticLocation" type="b" access="read"/>
+  <property name="Locations" type="av" access="read"/>
+
+  </interface>
+</node>
index 3352e0dcd7631406de6cc51bb6330be37ffcc359..21fdfa9496c81e28f0f0589d6b2f5733950f2174 100644 (file)
@@ -48,6 +48,7 @@
     <file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.Shell.Screenshot.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.xml</file>
+    <file preprocess="xml-stripblanks">org.gnome.Shell.WeatherIntegration.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.Shell.xml</file>
     <file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file>
     <file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file>
index 4aca92162b5206eb8c797c588588e3ce8a441254..9c3e42c944dc70da5ec1a63183283d3c64ea5cf7 100644 (file)
     </key>
   </schema>
 
+  <schema id="org.gnome.shell.weather" path="/org/gnome/shell/weather/"
+          gettext-domain="@GETTEXT_PACKAGE@">
+    <key name="automatic-location" type="b">
+      <summary>Automatic location</summary>
+      <description>
+        Whether to fetch the current location or not
+      </description>
+      <default>false</default>
+    </key>
+
+    <key name="locations" type="av">
+      <summary>Location</summary>
+      <description>
+        The location for which to show a forecast
+      </description>
+      <default>[]</default>
+    </key>
+  </schema>
+
   <!-- unused, change 00_org.gnome.shell.gschema.override instead -->
   <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
          gettext-domain="@GETTEXT_PACKAGE@">
index efd8ce82daa1b0c32b3a90499f4f7aeacdc056b4..4d63d745be6c6b1021c28985e9317bccada5a34b 100644 (file)
@@ -1,10 +1,19 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const { Geoclue, Gio, GLib, GWeather } = imports.gi;
+const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi;
 const Signals = imports.signals;
 
 const PermissionStore = imports.misc.permissionStore;
-const Util = imports.misc.util;
+
+const { loadInterfaceXML } = imports.misc.fileUtils;
+
+const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
+
+const WEATHER_BUS_NAME = 'org.gnome.Weather';
+const WEATHER_OBJECT_PATH = '/org/gnome/Weather';
+const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration';
+
+const WEATHER_APP_ID = 'org.gnome.Weather.desktop';
 
 // Minimum time between updates to show loading indication
 var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
@@ -66,17 +75,36 @@ var WeatherClient = class {
             this.emit('changed');
         });
 
-        this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
-                                                          'org.gnome.Weather');
-        this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
-        this._weatherAppMon.watchSetting('automatic-location',
-                                         this._onAutomaticLocationChanged.bind(this));
-        this._weatherAppMon.watchSetting('locations',
-                                         this._onLocationsChanged.bind(this));
+        this._weatherApp = null;
+        this._weatherProxy = null;
+
+        let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
+        Gio.DBusProxy.new(
+            Gio.DBus.session,
+            Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
+            nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
+            WEATHER_BUS_NAME,
+            WEATHER_OBJECT_PATH,
+            WEATHER_INTEGRATION_IFACE,
+            null,
+            this._onWeatherProxyReady.bind(this));
+
+        this._settings = new Gio.Settings({
+            schema_id: 'org.gnome.shell.weather'
+        });
+        this._settings.connect('changed::automatic-location',
+            this._onAutomaticLocationChanged.bind(this));
+        this._settings.connect('changed::locations',
+            this._onLocationsChanged.bind(this));
+
+        this._appSystem = Shell.AppSystem.get_default();
+        this._appSystem.connect('installed-changed',
+            this._onInstalledChanged.bind(this));
+        this._onInstalledChanged();
     }
 
     get available() {
-        return this._weatherAppMon.available;
+        return this._weatherApp != null;
     }
 
     get loading() {
@@ -92,7 +120,8 @@ var WeatherClient = class {
     }
 
     activateApp() {
-        this._weatherAppMon.activateApp();
+        if (this._weatherApp)
+            this._weatherApp.activate();
     }
 
     update() {
@@ -114,6 +143,37 @@ var WeatherClient = class {
                this._weatherAuthorized;
     }
 
+    _onWeatherProxyReady(o, res) {
+        try {
+            this._weatherProxy = Gio.DBusProxy.new_finish(res);
+        } catch (e) {
+            log(`Failed to create GNOME Weather proxy: ${e}`);
+            return;
+        }
+
+        this._weatherProxy.connect('g-properties-changed',
+            this._onWeatherPropertiesChanged.bind(this));
+
+        if (this._weatherProxy.g_owner != null)
+            this._onWeatherPropertiesChanged();
+    }
+
+    _onWeatherPropertiesChanged() {
+        this._settings.set_boolean('automatic-location',
+            this._weatherProxy.AutomaticLocation);
+        this._settings.set_value('locations',
+            new GLib.Variant('av', this._weatherProxy.Locations));
+    }
+
+    _onInstalledChanged() {
+        let hadApp = (this._weatherApp != null);
+        this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
+        let haveApp = (this._weatherApp != null);
+
+        if (hadApp !== haveApp)
+            this.emit('changed');
+    }
+
     _loadInfo() {
         let id = this._weatherInfo.connect('updated', () => {
             this._weatherInfo.disconnect(id);